home *** CD-ROM | disk | FTP | other *** search
/ ASME's Mechanical Engine…ing Toolkit 1997 December / ASME's Mechanical Engineering Toolkit 1997 December.iso / c_lang / tc-pull.lzh / TC_MENU.C < prev    next >
Encoding:
C/C++ Source or Header  |  1987-11-26  |  14.8 KB  |  570 lines

  1. /*
  2. **  TC_MENU.C
  3. **
  4. **  Turbo C version of James Pinson's Lattice C program PULLDOWN.C
  5. **
  6. **  I edited his program to suit my standard library (included) and
  7. **  to eliminate the warnings, also made adjustments for Turbo C.
  8. **
  9. **  Compile TC_ASM.C with   tcc -c tc_asm
  10. **
  11. **  then use TC_MENU.PRJ  to compile
  12. **
  13. **
  14. **    -- Rich S.
  15. */
  16.  
  17. #include <stdio.h>
  18. #include <ctype.h>
  19. #include <dos.h>
  20. #include <conio.h>
  21. #include <mem.h>
  22.  
  23.  
  24. #define NORMAL    7       /* change these as desired for color */
  25. #define HI_INTEN  15
  26. #define REVERSE   112
  27.  
  28. #define TRUE  1
  29. #define FALSE 0
  30.  
  31. unsigned int attribute;
  32. static char buff[4000];
  33.  
  34. #define  NU_MAIN 5        /* number of main menu options */
  35. #define  NU_SUB  5        /* number of sub menu options  */
  36.  
  37. int menu();
  38. int pull_down();
  39. void make_inst();
  40. void demo();
  41. void help();
  42. void clear_window();
  43. void menubox();
  44. void make_window();
  45. int get_key();
  46.  
  47.  
  48. struct menu_str           /* change this if you need more options */
  49. {
  50.      char *head;
  51.      char *body[NU_SUB];
  52.      void (*fun1)();
  53.      void (*fun2)();
  54.      void (*fun3)();
  55.      void (*fun4)();
  56.      void (*fun5)();
  57. };
  58.  
  59.  
  60. /*-----------*/
  61. /*  M A I N  */
  62. /*-----------*/
  63.  
  64. main()
  65. {
  66.      extern unsigned int attribute;
  67.      
  68.      int hi_attr, nor_attr;
  69.      
  70.      static struct menu_str m_menu[NU_MAIN] =
  71.      {
  72.           "   File   ",     /*  The first menu option */
  73.           "   Dir      ",   /*  Menu sub options */
  74.           "   Load     ",
  75.           "   Save     ",
  76.           "   Erase    ",
  77.           "   Path     ",
  78.           demo,             /* The functions each sub-option call */
  79.           demo,
  80.           demo,             /* these all call the same fake function */
  81.           demo,
  82.           demo,
  83.           
  84.           "   Locate ",     /* The second menu option */
  85.           " All-words  ",
  86.           " First-word ",
  87.           "\0",
  88.           "\0",             /* space filler for unused option names */
  89.           "\0",
  90.           demo,
  91.           demo,
  92.           0,                /* unused function pointer */
  93.           0,
  94.           0,
  95.           
  96.           "   Configure   ",    /* The third option */
  97.           " Modem ",
  98.           " Screen ",
  99.           " Printer ",
  100.           "\0",
  101.           "\0",
  102.           demo,
  103.           demo,
  104.           demo,
  105.           0,
  106.           0,
  107.           
  108.           "        Output       ",    /* The fourth menu option */
  109.           "  Screen  ",
  110.           "  Printer ",
  111.           "  Disk    ",
  112.           "  Modem   ",
  113.           "\0",
  114.           demo,
  115.           demo,
  116.           demo,
  117.           demo,
  118.           0,
  119.           
  120.           
  121.           " Help ",                       /* The fifth option */
  122.           " Instant help (really works) ",
  123.           "\0",
  124.           "\0",
  125.           "\0",
  126.           "\0",
  127.           help,
  128.           0,
  129.           0,
  130.           0,
  131.           0,
  132.      };
  133.      
  134.      
  135.      hi_attr = REVERSE;
  136.      nor_attr = NORMAL;
  137.      
  138.      attribute = nor_attr;
  139.      getscrn(buff);
  140.      cls();
  141.      cursor(0);              /* hide cursor */
  142.      
  143.      make_inst();          /* Show instructions */
  144.      
  145.      menu(m_menu, NU_MAIN, NU_SUB, hi_attr, nor_attr);
  146.      
  147.      putscrn(buff);        /* restore text display*/
  148.      cursor(1);            /* restore cursor      */
  149. }
  150.  
  151.  
  152. /*-----------*/
  153. /*  M E N U  */
  154. /*-----------*/
  155.  
  156. int menu(m_menu, nu_main, nu_sub, hi_attr, nor_attr)
  157. struct menu_str m_menu[];
  158. int nu_main, nu_sub, hi_attr, nor_attr;
  159. {
  160.      extern unsigned int attribute;
  161.      
  162.      int i, j, cur_x, cur_y, cur_opt, found, expert = 1;
  163.      char ch, ext,ltr;
  164.      
  165.      ch = ' ';
  166.      ext = ' ';
  167.      cur_opt = 0;
  168.      found = 0;
  169.      
  170.      attribute = nor_attr;
  171.      
  172.      make_window(0, 0, 78, 1, 1);
  173.      
  174.      for (;;)               /* endless loop */
  175.      {
  176.           for (i = 0; i < nu_main; i++)
  177.           {
  178.                j = 0;
  179.                while (m_menu[i].head[j] != '\0')
  180.                {
  181.                     ltr = m_menu[i].head[j];
  182.                     j++;
  183.                     if (ch == ltr && ch != ' ')
  184.                     {
  185.                          found = TRUE;
  186.                          cur_opt = i;
  187.                     }
  188.                }
  189.           }
  190.           if (ch == 13)
  191.           {
  192.                found = TRUE;
  193.                expert = FALSE;
  194.           }
  195.           
  196.           ch = ' ';
  197.           cur_x = 1;
  198.           cur_y = 1;
  199.           
  200.           for (i = 0; i < nu_main; i++)
  201.           {
  202.                if (i == cur_opt)
  203.                attribute = hi_attr;
  204.                else
  205.                attribute= nor_attr;
  206.                fastwrite(cur_x, cur_y,attribute, m_menu[i].head);
  207.                cur_x += strlen(m_menu[i].head) + 3;
  208.           }
  209.           
  210.           if (!expert)
  211.           found = TRUE;
  212.           
  213.           if (found)
  214.           {
  215.                ext = pull_down(m_menu, nu_sub, cur_opt); /* pull-down options */
  216.                if (ext == 27)
  217.                expert = TRUE;
  218.                if (ext == 'r' || ext == 'l')
  219.                expert = FALSE;
  220.                if (ext == 'r')
  221.                ++cur_opt;
  222.                if (ext == 'l')
  223.                --cur_opt;
  224.                ch = ' ';
  225.                ext = ' ';
  226.           }
  227.           
  228.           if (!found)
  229.           {
  230.                ch = ' ';
  231.                get_key(&ch, &ext);
  232.                ch = toupper(ch);
  233.           }
  234.           
  235.           if (ch == 27)
  236.           return;
  237.           
  238.           if (ext == 'r' || ext == 'l')
  239.           expert = 0;
  240.           if (ext == 'r')
  241.           ++cur_opt;
  242.           if (ext == 'l')
  243.           --cur_opt;
  244.           if (cur_opt >= nu_main)
  245.           cur_opt = 0;
  246.           if (cur_opt < 0)
  247.           cur_opt = nu_main - 1;
  248.           ext = ' ';
  249.           found = 0;
  250.           
  251.      }  /* end for (;;) */
  252. }
  253.  
  254.  
  255.  
  256. /*---------------------*/
  257. /*  P U L L _ D O W N  */
  258. /*---------------------*/
  259.  
  260. int pull_down(m_menu, nu_sub, position)
  261. struct menu_str m_menu[];
  262. int position;
  263. {
  264.      extern unsigned int attribute;
  265.      char ch = ' ', ltr;
  266.      int ext = ' ', hi_attr, nor_attr;
  267.      int i, j, tx, ty, start, width, nu_opt, cur_opt = 0, found = FALSE;
  268.      
  269.      nu_opt = nu_sub;
  270.      
  271.      /* nu_sub = number of possible pull-down options */
  272.      /* find out how many are in use */
  273.      
  274.      for (i = 0; i < nu_opt; i++)
  275.      {
  276.           if (m_menu[position].body[i][0] == '\0')
  277.           {
  278.                nu_opt = i;
  279.                break;
  280.           }
  281.      }
  282.      
  283.      hi_attr = REVERSE;
  284.      nor_attr = NORMAL;
  285.      
  286.      attribute = nor_attr;
  287.      
  288.      start = 1;    /* Figure where to draw pull-down box */
  289.      /* 1 is column to start 1st box */
  290.      /* Add up length of menu heads */
  291.      
  292.      for (i = 0; i < position; i++)
  293.      start += strlen(m_menu[i].head) + 3;
  294.      
  295.      width = 0;     /* figure max length of window */
  296.      
  297.      for (i = 0; i < nu_opt; i++)
  298.      if (strlen(m_menu[position].body[i]) > width)
  299.      width = strlen(m_menu[position].body[i]);
  300.      
  301.      /* move box to left if it will spill off right side */
  302.      
  303.      if (start + width + 1 > 79)
  304.      start = 79 - width - 2;
  305.      
  306.      getscrn(buff);
  307.      
  308.      make_window(start++, 2, width, nu_opt, 0);   /*make a window */
  309.      attribute = nor_attr;
  310.      
  311.      tx = start;   /* reposition for writing */
  312.      ty = 3;
  313.      
  314.      for (;;)
  315.      {
  316.           for (i = 0; i < nu_opt; i++)
  317.           {
  318.                if (i == cur_opt)
  319.                attribute = hi_attr;
  320.                else
  321.                attribute = nor_attr;
  322.                fastwrite(tx, ty++,attribute, m_menu[position].body[i]);
  323.           }
  324.           
  325.           attribute = nor_attr;
  326.           
  327.           if (found)
  328.           {
  329.                putscrn(buff);     /* remove box */
  330.                
  331.                /* If you want more than 5 menu options */
  332.                /* change this next switch statement    */
  333.                
  334.                switch(cur_opt)    /* call function */
  335.                {
  336.                     case 0: (*m_menu[position].fun1)(); break;
  337.                     case 1: (*m_menu[position].fun2)(); break;
  338.                     case 2: (*m_menu[position].fun3)(); break;
  339.                     case 3: (*m_menu[position].fun4)(); break;
  340.                     case 4: (*m_menu[position].fun5)(); break;
  341.                }
  342.                
  343.                /* found = FALSE; */
  344.                if (kbhit())
  345.                getch();  /* make sure keyboard buffer is clear */
  346.                return(' ');
  347.           }
  348.           
  349.           tx = start;
  350.           ty = 3;
  351.           get_key(&ch, &ext);  /* get a character */
  352.           ch = toupper(ch);
  353.           if (ext == 'd')
  354.           ++cur_opt;
  355.           if (ext == 'u')
  356.           --cur_opt;
  357.           if (cur_opt >= nu_opt)
  358.           cur_opt = 0;
  359.           if (cur_opt < 0)
  360.           cur_opt = nu_opt - 1;
  361.           
  362.           if (ch == 13)
  363.           found = TRUE;
  364.           
  365.           for (i = 0; i < nu_opt; i++)   /* does it match an option? */
  366.           {
  367.                j = 0;
  368.                while (m_menu[position].body[i][j] != '\0')
  369.                {
  370.                     ltr = m_menu[position].body[i][j];
  371.                     j++;
  372.                     if (ch == ltr)
  373.                     {
  374.                          cur_opt = i;
  375.                          found = TRUE;
  376.                     }
  377.                }
  378.           }
  379.           
  380.           if (ext == 'l'|| ext == 'r')
  381.           break;
  382.           
  383.           if (ch == 27)   /* EXIT IF ESCAPE KEY */
  384.           {
  385.                ext = ch;
  386.                break;
  387.           }
  388.           
  389.           ext = ' ';
  390.           ch = ' ';
  391.           
  392.      }   /* end for (;;) */
  393.      
  394.      putscrn(buff);
  395.      return (ext);
  396. }
  397. /*---------------------*/
  398. /*  M A K E _ I N S T  */
  399. /*---------------------*/
  400.  
  401. void make_inst()
  402. {
  403.      extern unsigned int attribute;
  404.      
  405.      attribute = NORMAL;
  406.      
  407.      fastwrite( 1,  4,attribute, "INSTRUCTIONS:");
  408.      fastwrite( 1,  6,attribute, "EXPERT MODE: Select by touching the key which represents each option.");
  409.      fastwrite(15,  7,attribute, "(the capital letter)");
  410.      
  411.      fastwrite( 1, 10,attribute, "ASSIST MODE: Pull-down menu by touching 'enter' or a cursor key.");
  412.      fastwrite(14, 11,attribute, "Select by highlighting with cursor keys- then touch return");
  413.      fastwrite(14, 13,attribute, "Return to Expert mode by touching 'escape'");
  414.      
  415.      fastwrite( 1, 15,attribute, "EXIT:        Touch 'Escape' while in expert mode.");
  416. }
  417.  
  418.  
  419. /*-----------*/
  420. /*  D E M O  */
  421. /*-----------*/
  422.  
  423. void demo()
  424. {
  425.      getscrn(buff);
  426.      make_window(19, 9, 40, 5, 1);
  427.      
  428.      fastwrite(21, 11,HI_INTEN, "Put your favorite routine here ");
  429.      fastwrite(21, 14,HI_INTEN, "touch any key to return to menu");
  430.      getch();
  431.      
  432.      putscrn(buff);
  433. }
  434.  
  435.  
  436. /*-----------*/
  437. /*  H E L P  */
  438. /*-----------*/
  439.  
  440. void help()
  441. {
  442.      attribute = NORMAL;
  443.      getscrn(buff);
  444.      
  445.      clear_window(0, 3, 80, 21);
  446.      fastwrite(1,  7,HI_INTEN, "This is a demonstration of a help screen.");
  447.      fastwrite(1,  9,HI_INTEN, "This text was written by means of direct memory address.");
  448.      fastwrite(1, 10,HI_INTEN, "The original screen has been saved and will be restored ");
  449.      fastwrite(1, 11,HI_INTEN, "when you exit this 'help' screen.");
  450.      fastwrite(1, 14,HI_INTEN, "Please touch any key to continue.");
  451.      
  452.      getch();
  453.      putscrn(buff);
  454. }
  455.  
  456.  
  457. /* Screen Function Library */
  458.  
  459. /*---------------------*/
  460. /*  S E T _ C O L O R  */
  461. /*---------------------*/
  462.  
  463. /* Call with foreground and background colors.  Returns attribute. */
  464.  
  465. int set_color(foreground, background)
  466. int foreground,background;
  467. {
  468.      return (background << 4 | foreground);
  469. }
  470.  
  471.  
  472.  
  473. /*---------------------------*/
  474. /*  C L E A R _ W I N D O W  */
  475. /*---------------------------*/
  476.  
  477. void clear_window(x, y, width, height)  /* Call with x,y of upper left   */
  478. unsigned int x, y, width, height;       /* corner of window area.        */
  479. {                                       /* Clears down and to right      */
  480.      extern unsigned int attribute;       /* Cleared with active attribute */
  481.      union REGS regist;                   /* Use on displayed page only!   */
  482.      
  483.      regist.x.ax = 0x0600;
  484.      regist.h.ch = y;
  485.      regist.h.cl = x;
  486.      regist.x.dx = (y + height - 1) << 8 | x + width - 1;
  487.      regist.h.bh = attribute;
  488.      int86(0x10, ®ist, ®ist);
  489. }
  490.  
  491.  
  492. /*---------*/
  493. /*  B O X  */
  494. /*---------*/
  495.  
  496. void menubox(x, y, width, height, type)    /* type 0 = pull-down box */
  497. int x, y, width, height, type;         /* type 1 = regular box   */
  498. {
  499.      extern unsigned int attribute; 
  500.      int i, u_right, u_left;
  501.      char string[82];
  502.      
  503.      if (type == 0)           /* following sets corners */
  504.      {
  505.           u_left  = 194;
  506.           u_right = 194;
  507.      }
  508.      else if (type == 1)
  509.      {
  510.           u_left  = 218;
  511.           u_right = 191;
  512.      }
  513.      
  514.      string[0] = u_left;
  515.      for (i = 1; i <= width; string[i++] = 196);
  516.      string[i++] = u_right;
  517.      string[i] = '\0';
  518.      fastwrite(x, y++,attribute, string);
  519.      
  520.      for (i = 0; i < height; i++)
  521.      {
  522.           fastwrite(x, y,attribute, "\xB3");
  523.           fastwrite(x + width + 1, y++,attribute, "\xB3");
  524.      }
  525.      
  526.      string[0]=192;
  527.      for(i = 1; i <= width; string[i++] = 196);
  528.      string[i++] = 217;
  529.      string[i] = '\0';
  530.      fastwrite(x, y++,attribute, string);
  531. }
  532.  
  533. /*-------------------------*/
  534. /*  M A K E _ W I N D O W  */
  535. /*-------------------------*/
  536.  
  537. void make_window(x, y, width, height, type)  /* Draws and clears a box */
  538. unsigned int x, y, width, height, type;
  539. {
  540.      menubox(x++, y++, width, height, type);    /* Draw box */
  541.      clear_window(x, y, width, height);     /* Clear interior */
  542. }
  543.  
  544. /*-----------------*/
  545. /*  G E T _ K E Y  */
  546. /*-----------------*/
  547.  
  548. int get_key(ch, ext)          /* Read a char             */
  549. char *ch;                     /* Return character in ch  */
  550. int *ext;                     /* If it is a function key */
  551. {                             /* return following in ext */
  552.      *ch = getch();             /*   up-arrow    = 'u'     */
  553.      if (!*ch)                  /*   down-arrow  = 'd'     */
  554.      {                       /*   right-arrow = 'r'     */
  555.           *ext = getch();         /*   left-arrow  = 'l'     */
  556.           switch (*ext)
  557.           {
  558.                case 'H': *ext = 'u'; break;  /*  up      */
  559.                case 'P': *ext = 'd'; break;  /*  down    */
  560.                case 'M': *ext = 'r'; break;  /*  right   */
  561.                case 'K': *ext = 'l'; break;  /*  left    */
  562.                case 'G': *ext = 'h'; break;  /*  home    */
  563.                case 'O': *ext = 'e'; break;  /*  end     */
  564.                case 'R': *ext = 'I'; break;  /*  insert  */
  565.                case 'S': *ext = 'D'; break;  /*  delete  */
  566.           }
  567.      }
  568. }
  569.  
  570.